package com.emm.yixun.system.service.impl.pmo;

import com.emm.yixun.basic.service.*;
import com.emm.yixun.common.enums.CustomerLevelEnum;
import com.emm.yixun.common.enums.IndustMarkEnums;
import com.emm.yixun.common.enums.IndustTypeEnums;
import com.emm.yixun.common.model.*;
import com.emm.yixun.common.model.dto.*;
import com.emm.yixun.common.model.enums.CodeTypeEnum;
import com.emm.yixun.common.model.enums.DelFlagEnum;
import com.emm.yixun.common.model.enums.ObjectTypeEnum;
import com.emm.yixun.common.model.enums.SaleReturnEnum;
import com.emm.yixun.common.model.pmo.*;
import com.emm.yixun.common.response.Response;
import com.emm.yixun.common.response.ResponseList;
import com.emm.yixun.common.utils.DateStyle;
import com.emm.yixun.common.utils.DateUtils;
import com.emm.yixun.common.utils.MathUtil;
import com.emm.yixun.system.service.pmo.PmoDynamicDataServiceFacade;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.jws.WebService;
import java.math.BigDecimal;
import java.util.*;

@Service("pmoDynamicDataServiceFacade")
@WebService(name = "com.emm.yixun.system.service.pmo.PmoDynamicDataServiceFacade")
public class PmoDynamicDataFacadeImpl implements PmoDynamicDataServiceFacade {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private ProjectService projectService;
	@Autowired
	private ProjectPremisesService projectPremisesService;
	@Autowired
	private ProjectPmoService projectPmoService;
	@Autowired
	private ProjectPremisesIndustDataService projectPremisesIndustDataService;
	@Autowired
	private ProjectPremisesPmoService projectPremisesPmoService;
	@Autowired
	private SaleReturnPmoService salereturnpmoservice;
	@Autowired
	private BaseCodeValueService baseCodeValueService;
	@Autowired
	private CustomerService customerService;
	@Autowired
	private SignedService signedService;

	@Override
	public Response<LevelDynamiSalesData> quereyLevelDynamiSalesData(String pmoProjectCode, String month) {
		Response<LevelDynamiSalesData> response = new Response<LevelDynamiSalesData>();
		try {
			ProjectPmoDto projectPmoDto = new ProjectPmoDto();
			projectPmoDto.setPmoProjectCode(pmoProjectCode);
			ProjectPmo projectPmo = projectPmoService.selectByDto(projectPmoDto);
			if (null == projectPmo) {
				response.fail("100004", "项目编码:" + pmoProjectCode + "不存在!");
			} else {
				String calYear = month.substring(0,4);
				String calYearMonth = month.substring(0,4) + "-" + month.substring(4);
				PmoSaleDataDto psdDto = new PmoSaleDataDto();
				psdDto.setProjectId(projectPmo.getProjectId());
				psdDto.setCalYear(calYear);
				//psdDto.setCalMonth(calYearMonth);
				//签约记录业态统计
				List<PmoSignedDataDto> signedDataList = projectService.queryPmoSignedData(psdDto);
				//回款记录业态统计
				List<PmoReceivedDataDto> receivedDataList = projectService.queryPmoReceivedData(psdDto);

				//项目所有业态
				ProjectPremisesIndustDataDto queryIndustData = new ProjectPremisesIndustDataDto();
				queryIndustData.setProjectId(projectPmo.getProjectId());
				queryIndustData.setDelFlag(DelFlagEnum.UNDEL.getNo());
				List<ProjectPremisesIndustData> allIndustList = projectPremisesIndustDataService.selectListByDto(queryIndustData);

				LevelDynamiSalesData levelDynamiSalesData = createLevelDynamiSalesData(calYearMonth, projectPmo, signedDataList, receivedDataList, allIndustList);
				response.success(levelDynamiSalesData);
			}

		} catch (Exception e) {
			e.printStackTrace();
			logger.error("查询动态销售数据:" + e);
			response.fail("000005", "数据库操作异常");
		}
		return response;
	}

	private LevelDynamiSalesData createLevelDynamiSalesData(String yearMonth, ProjectPmo projectPmo, List<PmoSignedDataDto> signedDataList, List<PmoReceivedDataDto> receivedDataList, List<ProjectPremisesIndustData> allIndustList) {
		Long projectId = projectPmo.getProjectId();
		// 项目级业态动态数据
		List<DynamiSalesDataExtend> list = createIndustDataList(yearMonth,"project", projectPmo.getProjectId(), null, signedDataList, receivedDataList, allIndustList);

		// 分期级业态动态数据
		List<LevelDynamiSalesData> ztList = createPremisesSalesDatas(yearMonth,"premises", projectPmo.getProjectId(), null, signedDataList, receivedDataList, allIndustList);
		LevelDynamiSalesData levelDynamiSalesData = new LevelDynamiSalesData();
		levelDynamiSalesData.setProjectCode(projectPmo.getPmoProjectCode());
		levelDynamiSalesData.setLevel("project");
		levelDynamiSalesData.setStageNumber(ztList.size());
		// 组装项目
		levelDynamiSalesData.setData(createDynamiSalesData(list, null, projectId, yearMonth, signedDataList, receivedDataList, allIndustList));
		// 组装组团
		levelDynamiSalesData.setDynamiSalesDatas(ztList);
		// 组装客户情况
		levelDynamiSalesData.setClientDatas(getClientLevel(projectId, yearMonth));
		List<DynamiSalesIndustData> industList = levelDynamiSalesData.getData().getIndust();
		//如果是月初就继承上月底的数据
		levelDynamiSalesData.getData().setIndust(convertIndustData(industList, projectId));
		// 组装业态
		return levelDynamiSalesData;

	}

	/**
	 * 根据业态,计算业态最近的一次交易相关数据.
	 * 触发条件: 当月当动态销售数据为空的时候
	 * @param list
	 * @param projectId
	 * @return
	 */
	public List<DynamiSalesIndustData> convertIndustData(List<DynamiSalesIndustData> list,Long projectId) {
		if(list!=null && !list.isEmpty()) {
			BaseCodeValueDto bcvDto = new BaseCodeValueDto();
			bcvDto.setCodeType(CodeTypeEnum.CUSTOMER_02.getNo());
			Map<String, BaseCodeValueDto> bcvMap = baseCodeValueService.selectBcvMap(bcvDto);

			for (DynamiSalesIndustData data : list) {
				//查询业态最近的交易数据
				Date date = signedService.findMaxSignedCheckDate(projectId, data.getIndustMark());
				if (date != null) {
					String month = DateUtils.DateToString(date, DateStyle.YYYY_MM);
					Map<String, Date> map =  dateConvert(month);
					Date beginDate = map.get("beginDate");
					Date endDate = map.get("endDate");

					for (Map.Entry<String, BaseCodeValueDto> entry : bcvMap.entrySet()) {
						bcvDto = entry.getValue();
						if(null != bcvDto && bcvDto.getCodeValue().equals(data.getIndustMark())){
							break;
						}else{
							bcvDto = null;
						}
					}
					if(null == bcvDto){
						continue;
					}

					PmoSaleDataDto psdDto = new PmoSaleDataDto();
					psdDto.setProjectId(projectId);
					psdDto.setCalMonth(month);
					//签约记录业态统计
					List<PmoSignedDataDto> signedDataList = projectService.queryPmoSignedData(psdDto);
					PmoSaleData sale = filterPmoSaleData(projectId, null, String.valueOf(bcvDto.getId()), null,signedDataList, null, month);

					//PmoSaleData oldSale = 	queryPmoSaleData(projectId, null, bcvDto.getId().toString(), null,beginDate, endDate);
					if(null != sale && null != sale.getTotalSignAmount() && sale.getTotalCalculateArea().compareTo(BigDecimal.ZERO)!=0) {
						BigDecimal totalSignAmount = sale.getTotalSignAmount().divide(new BigDecimal("10000"));
						if(data.getIndustMark().equals("parkingSpace")) { //车位
							data.getIndustData().setDynamicSalesaveragPrice(MathUtil.bigDivide(totalSignAmount, new BigDecimal(sale.getTotalRowCount()), 2));
						}else {
							data.getIndustData().setDynamicSalesaveragPrice(MathUtil.bigDivide(totalSignAmount, sale.getTotalCalculateArea(), 2));
						}
					}
				}
			}
		}
		return list;
	}

	public List<ClientData> getClientLevel(Long projectId, String month) {
		ClientDataParams params = new ClientDataParams();
		params.setProjectId(projectId);
		Map<String, Date> maps = dateConvert(month);
		Date beginDate = maps.get("beginDate");
		Date endDate = maps.get("endDate");
		params.setStartTime(DateUtils.DateToString(beginDate, DateStyle.YYYY_MM_DD_HH_MM_SS.getValue()));
		params.setEndTime(DateUtils.DateToString(endDate, DateStyle.YYYY_MM_DD_HH_MM_SS.getValue()));
		List<ClientData> list = customerService.queryCustomerLevelByPmo(params);
		if (list != null && !list.isEmpty()) {
			for (ClientData data : list) {
				CustomerLevelEnum level = CustomerLevelEnum.getCustomerLevel(data.getLevel());
				if (level != null) {
					data.setLevel(level.getName());
				}
			}
		}
		return list;
	}

	/**
	 * 
	 * getReasonActualSalesDeviat:销售额偏差原因,回款额偏差原因, 动态货值偏差原因<br/>
	 *
	 * @author Administrator
	 * @param projectId
	 * @param premisesId
	 * @param month
	 * @return
	 * @since JDK 1.6
	 */
	private String getReasonActualSalesDeviat(Long projectId, Long premisesId, String month,
			SaleReturnEnum saleReturnEnum) {
		SaleReturnPmoDto saleReturnPmoDto = new SaleReturnPmoDto();
		if (premisesId != null) {
			saleReturnPmoDto.setObjectId(premisesId);
			saleReturnPmoDto.setObjectType(ObjectTypeEnum.PREMISES.getNo());
		} else {
			saleReturnPmoDto.setObjectId(projectId);
			saleReturnPmoDto.setObjectType(ObjectTypeEnum.PROJECT.getNo());
		}
		saleReturnPmoDto.setSaleReturn(saleReturnEnum.getNo());
		if (saleReturnEnum.getNo().equals("3")) {
			String monthStr = month.substring(4, 6);
			if (monthStr.startsWith("0")) {
				monthStr = month.substring(5, 6);
			} else {
				monthStr = month.substring(4, 6);
			}
			saleReturnPmoDto.setSaleMonth(monthStr);
		} else {
			saleReturnPmoDto.setSaleMonth(month.substring(4, 6));
		}
		saleReturnPmoDto.setSaleYear(month.substring(0, 4));
		List<SaleReturnPmo> srpList = salereturnpmoservice.selectListByDto(saleReturnPmoDto);
		if (null != srpList && srpList.size() > 0) {
			return srpList.get(0).getSaleDiffReason();
		}
		return null;

	}

	/**
	 * 
	 * createDynamiSalesData:(这里用一句话描述这个方法的作用). <br/>
	 * 动态销售数据汇总 项目/分期
	 * 
	 * @author Administrator
	 * @param list
	 * @param premisesId
	 * @param projectId
	 * @param yearMonth
	 * @return
	 * @since JDK 1.6
	 */
	private DynamiSalesData createDynamiSalesData(List<DynamiSalesDataExtend> list, Long premisesId, Long projectId,
			String yearMonth, List<PmoSignedDataDto> signedDataList, List<PmoReceivedDataDto> receivedDataList, List<ProjectPremisesIndustData> allIndustList) {
		DynamiSalesData dsde = new DynamiSalesData();
		dsde.setDynamiExtend(list);
		dsde.setMonth(yearMonth.replace("-", ""));
		// 销售额偏差原因
		dsde.setReasonActualSalesDeviat(getReasonActualSalesDeviat(projectId, premisesId, yearMonth, SaleReturnEnum.SALE));
		// 回款额偏差原因
		dsde.setReasonActualBackAmountDeviat(getReasonActualSalesDeviat(projectId, premisesId, yearMonth, SaleReturnEnum.RETURN));
		// 动态货值偏差原因
		dsde.setReasonDynamiValueDeviat(getReasonActualSalesDeviat(projectId, premisesId, yearMonth, SaleReturnEnum.DYNAMIC));

		List<DynamiSalesIndustData> indust = new ArrayList<DynamiSalesIndustData>();
		// 动态货值汇总
		BigDecimal roomDynamiValue = BigDecimal.ZERO;
		// 车位动态货值汇总
		BigDecimal carDynamiValue = BigDecimal.ZERO;
		// 未售面积汇总
		BigDecimal unsoldArea = BigDecimal.ZERO;
		// 未售车位汇总
		BigDecimal cwUnsoldParkinSpace = BigDecimal.ZERO;
		// 房间实际销售额
		BigDecimal actualSalesAmount = BigDecimal.ZERO;
		// 车位实际销售额
		BigDecimal carActualSalesAmount = BigDecimal.ZERO;
		BigDecimal totalSalableAcreag = BigDecimal.ZERO;
		for (DynamiSalesDataExtend dynamiSalesDataExtend : list) {
			// 目标货值
			String industMark = dynamiSalesDataExtend.getIndustMark();
			DynamiSalesIndustData dynamiSalesIndustData = new DynamiSalesIndustData();
			dynamiSalesIndustData.setParentId(dynamiSalesDataExtend.getParentId());
			dynamiSalesIndustData.setIndustMark(dynamiSalesDataExtend.getIndustMark());
			DynamiSalesFieldIndustData dynamiSalesFieldIndustData = new DynamiSalesFieldIndustData();
			dsde.setTargetValue(dynamiSalesDataExtend.getTargetValue());
			if (industMark.equals(IndustMarkEnums.INDUSTMARKENUMS_PARKINSPACE.getCode())) {
				// 车位动态货值
				dynamiSalesFieldIndustData.setAveragPriceOfParkinSpace(dynamiSalesDataExtend.getAveragPriceOfParkinSpace());
				if (dynamiSalesDataExtend.getCwDynamiAveragPrice() != null) {
					carDynamiValue = carDynamiValue.add(dynamiSalesDataExtend.getCwDynamiAveragPrice());
				}

				if (dynamiSalesDataExtend.getTotalNoCalculateArea() != null) {
					cwUnsoldParkinSpace = cwUnsoldParkinSpace.add(dynamiSalesDataExtend.getTotalNoCalculateArea());
				}
			
				if (dynamiSalesDataExtend.getMonthActualSalesAmount() != null) {
					carActualSalesAmount = carActualSalesAmount.add(dynamiSalesDataExtend.getMonthActualSalesAmount());
				}
			} else {
				if (dynamiSalesDataExtend.getTotalSalableAcreag() != null) {
					totalSalableAcreag = totalSalableAcreag.add(dynamiSalesDataExtend.getTotalSalableAcreag());
				}
				// 房间动态货值
				if (dynamiSalesDataExtend.getDynamiValue() != null)
					roomDynamiValue = roomDynamiValue.add(new BigDecimal(dynamiSalesDataExtend.getDynamiValue()));
				// 动态货值
				dynamiSalesFieldIndustData.setDynamiValue(dynamiSalesDataExtend.getDynamiValue());
				// 已售面积
				dynamiSalesFieldIndustData.setSoldAcreag(dynamiSalesDataExtend.getSoldAcreag());
				// 动态均价
				dynamiSalesFieldIndustData.setDynamiAveragPrice(dynamiSalesDataExtend.getDynamiAveragPrice());
				if (dynamiSalesDataExtend.getMonthActualSalesAmount() != null)
					actualSalesAmount = actualSalesAmount.add(dynamiSalesDataExtend.getMonthActualSalesAmount());
			}

			PmoSaleData industMarkSale = filterPmoSaleData(projectId, premisesId, dynamiSalesDataExtend.getId().toString(), null,signedDataList, receivedDataList, yearMonth);
			if (industMarkSale != null && industMarkSale.getTotalCalculateArea()!=null &&industMarkSale.getTotalCalculateArea().compareTo(BigDecimal.ZERO)!=0) {
				if (industMarkSale.getTotalSignAmount() != null && industMarkSale.getTotalRowCount() != null
						&& industMarkSale.getTotalRowCount().compareTo(0L) != 0) {
					BigDecimal result = MathUtil.divide(industMarkSale.getTotalSignAmount().divide(new BigDecimal("10000")),
							industMarkSale.getTotalCalculateArea());
					dynamiSalesFieldIndustData.setDynamicSalesaveragPrice(result);
				}
			}
			dynamiSalesIndustData.setIndustData(dynamiSalesFieldIndustData);
			indust.add(dynamiSalesIndustData);
		}
		dsde.setIndust(indust);
		// 未售面积 = 可售-已售
		PmoSaleData querySales = filterPmoSaleData(projectId, premisesId, null, "1",signedDataList, receivedDataList, null);
		BigDecimal soldAcreag = null;
		if (querySales != null && querySales.getTotalCalculateArea() != null) {
			soldAcreag = MathUtil.bigDivide(querySales.getTotalCalculateArea(), new BigDecimal("10000"), 6);
		}
		if (soldAcreag == null && totalSalableAcreag != null) {
			unsoldArea = totalSalableAcreag;
		} else if (soldAcreag != null && totalSalableAcreag.compareTo(soldAcreag) > 0) {
			unsoldArea = totalSalableAcreag.subtract(soldAcreag);
		}
		// 已售车位数
		PmoSaleData saleCar = filterPmoSaleData(projectId, premisesId, null, "2",signedDataList, receivedDataList, null);
		if (saleCar.getTotalRowCount() != null && saleCar.getTotalRowCount().compareTo(0L) > 0) {
			dsde.setSoldParkinSpace(saleCar.getTotalRowCount().intValue());
		}
		if (roomDynamiValue.compareTo(BigDecimal.ZERO) != 0 )
			dsde.setDynamiValue(MathUtil.round(roomDynamiValue.add(carDynamiValue), 6)); //动态货值  = 房间动态货值+ 车位动态货值 2018/06/19
		if (carDynamiValue.compareTo(BigDecimal.ZERO) != 0)
			dsde.setCwDynamiValue(carDynamiValue);
		if (soldAcreag != null && soldAcreag.compareTo(BigDecimal.ZERO) != 0)
			dsde.setSoldAcreag(MathUtil.round(soldAcreag, 6));
		if (unsoldArea.compareTo(BigDecimal.ZERO) != 0)
			dsde.setUnsoldArea(unsoldArea);
		if (cwUnsoldParkinSpace.compareTo(BigDecimal.ZERO) != 0)
			dsde.setCwUnsoldParkinSpace(cwUnsoldParkinSpace.intValue());
		ProjectPremisesIndustDataDto queryIndust = new ProjectPremisesIndustDataDto();
		queryIndust.setProjectId(projectId);
		if (premisesId != null) {
			queryIndust.setPremisesId(premisesId);
			queryIndust.setIndustType("1");
		} else {
			queryIndust.setIndustType("0");
		}
		List<ProjectPremisesIndustData> industList = projectPremisesIndustDataService.selectListByDto(queryIndust);
		BigDecimal unit = new BigDecimal("10000");

		//此处疑惑: 字段actualSalesAmount,actualBackAmount
		//原统计的是所有业态某月金额,而不是全年金额.现已改成统计全年所有业态金额.
		//如果需要变更成统计月金额,将filterPmoSaleData方法中的最后一个字段设为yearMonth即可
		PmoSaleData currerPmoSaleData = filterPmoSaleData(projectId, premisesId, null, null,signedDataList, receivedDataList, yearMonth);
		BigDecimal totalSignAmount = currerPmoSaleData.getTotalSignAmount();
		BigDecimal haveSignedAmount = currerPmoSaleData.getTotalHaveReceive();
		if (currerPmoSaleData.getTotalSignAmount() != null
				&& currerPmoSaleData.getTotalSignAmount().compareTo(BigDecimal.ZERO) != 0) {
			totalSignAmount = MathUtil.bigDivide(totalSignAmount, unit, 6);
			// 汇总实际销售额
			dsde.setActualSalesAmount(totalSignAmount.doubleValue());
		} else {
			dsde.setActualSalesAmount(new Double(BigDecimal.ZERO.toString()));
		}
		if (haveSignedAmount != null && haveSignedAmount.compareTo(BigDecimal.ZERO) != 0) {
			haveSignedAmount = MathUtil.bigDivide(haveSignedAmount, unit, 6);
			dsde.setActualBackAmount(haveSignedAmount.doubleValue());
		} else {
			dsde.setActualBackAmount(new Double(BigDecimal.ZERO.toString()));
		}
		if (null != industList && industList.size() > 0) { 
			// 面积目标销售均价汇总
			BigDecimal targetAveragPrice = BigDecimal.ZERO;
			// 车位目标销售均价汇总
			BigDecimal cwTargetAveragPrice = BigDecimal.ZERO;
			// 可售面积汇总
			BigDecimal salableAcreag = BigDecimal.ZERO;
			// 可售车位数汇总
			BigDecimal cwSalableAcreag = BigDecimal.ZERO;

			BaseCodeValueDto bcvDto = new BaseCodeValueDto();
			bcvDto.setCodeType(CodeTypeEnum.CUSTOMER_02.getNo());
			Map<String, BaseCodeValueDto> bcvMap = baseCodeValueService.selectBcvMap(bcvDto);

			for (ProjectPremisesIndustData ppData : industList) {
				bcvDto = bcvMap.get(ppData.getIndustMark());
				// 车位
				if (bcvDto.getCodeValue().equals(IndustMarkEnums.INDUSTMARKENUMS_PARKINSPACE.getCode())) {
					if (ppData.getTargetAveragPrice() != null)
						cwTargetAveragPrice = cwTargetAveragPrice.add(ppData.getTargetAveragPrice());
					if (ppData.getSalableAcreag() != null)
						cwSalableAcreag = cwSalableAcreag.add(ppData.getSalableAcreag());
				} else { // 面积
					if (ppData.getTargetAveragPrice() != null)
						targetAveragPrice = targetAveragPrice.add(ppData.getTargetAveragPrice());
					if (ppData.getSalableAcreag() != null)
						salableAcreag = salableAcreag.add(ppData.getSalableAcreag());
				}

			}
			// 面积动态均价 =动态货值/可售面积
			if (roomDynamiValue.compareTo(BigDecimal.ZERO) != 0 && salableAcreag.compareTo(BigDecimal.ZERO) != 0) {
				dsde.setDynamiAveragPrice(
						MathUtil.bigDivide(roomDynamiValue, unit.multiply(salableAcreag), 6).doubleValue());
			}
			// 车位动态均价 = 车位动态货值/可售车位数
			if (cwTargetAveragPrice.compareTo(BigDecimal.ZERO) != 0
					&& cwUnsoldParkinSpace.compareTo(BigDecimal.ZERO) != 0) {
				BigDecimal result = carActualSalesAmount.add(cwTargetAveragPrice.multiply(cwUnsoldParkinSpace));
				dsde.setAveragPriceOfParkinSpace(MathUtil.bigDivide(result, cwSalableAcreag, 6).doubleValue());
			}
		

			
		}
		return dsde;
	}

	/**
	 * 
	 * createPremisesSalesDatas:组团的业态动态数据 <br/>
	 * 
	 * @author Administrator
	 * @param projectId
	 * @param yearMonth
	 * @return
	 * @since JDK 1.6
	 */
	public List<LevelDynamiSalesData> createPremisesSalesDatas(String yearMonth, String type, Long projectId, Long premisesId, List<PmoSignedDataDto> signedDataList, List<PmoReceivedDataDto> receivedDataList, List<ProjectPremisesIndustData> allIndustList) {
		List<LevelDynamiSalesData> resultList = new ArrayList<LevelDynamiSalesData>();
		ProjectPremisesDto premisesDto = new ProjectPremisesDto();
		premisesDto.setProjectId(projectId);
		premisesDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		List<ProjectPremises> projectPremisesList = projectPremisesService.selectListByDto(premisesDto);
		if(null != projectPremisesList && projectPremisesList.size() > 0){
			/**
			 * PMO组团信息
			 */
			ProjectPremisesPmoDto pppDto = new ProjectPremisesPmoDto();
			pppDto.setProjectId(projectId);
			List<ProjectPremisesPmo> pppList = projectPremisesPmoService.selectListByDto(pppDto);
			Map<Long, ProjectPremisesPmo> pppMap = new HashMap<>();
			if(null != pppList && pppList.size() > 0){
				for(ProjectPremisesPmo ppp: pppList){
					pppMap.put(ppp.getPremisesId(), ppp);
				}
			}

			for (ProjectPremises premisesObj : projectPremisesList) {
				ProjectPremisesPmo projectPremisesPmo = pppMap.get(premisesObj.getId());
				if (null != projectPremisesPmo) {
					List<DynamiSalesDataExtend> list = createIndustDataList(yearMonth,"premises", projectId, premisesObj.getId(), signedDataList, receivedDataList, allIndustList);
					LevelDynamiSalesData levelDynamiSalesData = new LevelDynamiSalesData();
					levelDynamiSalesData.setPremisesId(premisesObj.getId());
					levelDynamiSalesData.setProjectCode(projectPremisesPmo.getPmoPremisesCode());
					levelDynamiSalesData.setLevel("phaseStaging");
					levelDynamiSalesData.setData(createDynamiSalesData(list, premisesObj.getId(), projectId, yearMonth, signedDataList, receivedDataList, allIndustList));
					resultList.add(levelDynamiSalesData);
				}
			}
		}
		return resultList;
	}

	/**
	 * 根据类型,从项目下所有类型中获取项目或组团业态
	 * @param type
	 * @param allIndustList
	 * @return
	 */
	public List<ProjectPremisesIndustData> filterIndust(String type, List<ProjectPremisesIndustData> allIndustList){
		List<ProjectPremisesIndustData> industList = new ArrayList<>();
		if (null != allIndustList && allIndustList.size() > 0) {
			for(ProjectPremisesIndustData ppid: allIndustList){
				if("project".equals(type)){
					if(ppid.getIndustType().equals(IndustTypeEnums.PROJECT.getCode())){
						industList.add(ppid);
					}
				}else if("premises".equals(type)){
					if(ppid.getIndustType().equals(IndustTypeEnums.PREMISES.getCode())){
						industList.add(ppid);
					}
				}
			}
		}
		return industList;
	}

	/**
	 * 获取项目或组团相关业态销售数据
	 * @param projectId 项目
	 * @param premisesId 组团
	 * @param industMark 业态
	 *        此处为null时,匹配项目或组团统计数据
	 * @param isRoom 是否房源
	 * 		  此处为null时,匹配所有房源,不区分房源后车位
	 * @param signedDataList 签约统计数据
	 *        此处为null时,代表无统计数据
	 * @param receivedDataList 收款统计数据
 	*         此处为null时,代表无统计数据
	 * @param matchMonth 匹配月份
	 *        此处为null时,代表获取的数据中有指定具体月份,格式: 年-月
	 * @return
	 */
	public PmoSaleData filterPmoSaleData(Long projectId, Long premisesId, String industMark, String isRoom,
			List<PmoSignedDataDto> signedDataList, List<PmoReceivedDataDto> receivedDataList, String matchMonth){

		PmoSaleData pmoSaleData = new PmoSaleData();
		//签约相关数据
		int totalRowCount = 0;
		BigDecimal totalCalculateArea = BigDecimal.ZERO;
		BigDecimal totalSignAmount = BigDecimal.ZERO;
		//是否需要检验业态
		boolean industMarkFlag = false;
		boolean matchMonthFlag = false;
		boolean isRoomFlag = false;
		if(null != signedDataList && signedDataList.size() > 0){
			for(PmoSignedDataDto psdDto: signedDataList){
				industMarkFlag = false;
				matchMonthFlag = false;
				isRoomFlag = false;
				if(StringUtils.isBlank(psdDto.getIndustMark()) || StringUtils.isBlank(industMark) || psdDto.getIndustMark().equals(industMark)){
					industMarkFlag = true;
				}
				if(StringUtils.isBlank(matchMonth) || psdDto.getCalMonth().equals(matchMonth)){
					matchMonthFlag = true;
				}
				if(StringUtils.isBlank(psdDto.getIsRoom()) || StringUtils.isBlank(isRoom) || psdDto.getIsRoom().equals(isRoom)){
					isRoomFlag = true;
				}
				BigDecimal psdCalArea = psdDto.getTotalCalculateArea() == null ? BigDecimal.ZERO:psdDto.getTotalCalculateArea();
				BigDecimal psdSignAmount = psdDto.getTotalSignAmount() == null ? BigDecimal.ZERO:psdDto.getTotalSignAmount();
				//检验是否只查询指定类型房源: 1、房源 2、车位
				if(StringUtils.isNotBlank(isRoom)){
					if(null != premisesId){
						//分期不为空,同时校验项目及分期及房源类型相等字段相等
						if(psdDto.getProjectId().equals(String.valueOf(projectId))
							&& psdDto.getPremisesId().equals(String.valueOf(premisesId))
							&& industMarkFlag
							&& matchMonthFlag
							&& isRoomFlag){
							totalRowCount += psdDto.getTotalRowCount();
							totalCalculateArea = totalCalculateArea.add(psdCalArea);
							totalSignAmount = totalSignAmount.add(psdSignAmount);
						}
					}else{
						//分期为空,只校验项目相等
						//分期不为空,同时校验项目及分期字段相等
						if(psdDto.getProjectId().equals(String.valueOf(projectId))
							&& industMarkFlag
							&& matchMonthFlag
							&& isRoomFlag){
							totalRowCount += psdDto.getTotalRowCount();
							totalCalculateArea = totalCalculateArea.add(psdCalArea);
							totalSignAmount = totalSignAmount.add(psdSignAmount);
						}
					}
				}else{
					if(null != premisesId){
						//分期不为空,同时校验项目及分期及房源类型相等字段相等
						if(psdDto.getProjectId().equals(String.valueOf(projectId))
								&& psdDto.getPremisesId().equals(String.valueOf(premisesId))
								&& industMarkFlag
								&& matchMonthFlag){
							totalRowCount += psdDto.getTotalRowCount();
							totalCalculateArea = totalCalculateArea.add(psdCalArea);
							totalSignAmount = totalSignAmount.add(psdSignAmount);
						}
					}else{
						//分期为空,只校验项目相等
						//分期不为空,同时校验项目及分期字段相等
						if(psdDto.getProjectId().equals(String.valueOf(projectId))
								&& industMarkFlag
								&& matchMonthFlag){
							totalRowCount += psdDto.getTotalRowCount();
							totalCalculateArea = totalCalculateArea.add(psdCalArea);
							totalSignAmount = totalSignAmount.add(psdSignAmount);
						}
					}
				}
			}
		}
		//收款相关数据
		BigDecimal totalHaveReceive = BigDecimal.ZERO;
		if(null != receivedDataList && receivedDataList.size() > 0){
			for(PmoReceivedDataDto prdDto: receivedDataList){
				industMarkFlag = false;
				matchMonthFlag = false;
				isRoomFlag = false;
				if(StringUtils.isBlank(prdDto.getIndustMark()) || StringUtils.isBlank(industMark) || prdDto.getIndustMark().equals(industMark)){
					industMarkFlag = true;
				}
				if(StringUtils.isBlank(matchMonth) || prdDto.getCalMonth().equals(matchMonth)){
					matchMonthFlag = true;
				}
				if(StringUtils.isBlank(prdDto.getIsRoom()) || StringUtils.isBlank(isRoom) || prdDto.getIsRoom().equals(isRoom)){
					isRoomFlag = true;
				}
				BigDecimal prdHaveReceive = prdDto.getTotalHaveReceive() == null ? BigDecimal.ZERO:prdDto.getTotalHaveReceive();
				//检验是否只查询指定类型房源: 1、房源 2、车位
				if(StringUtils.isNotBlank(isRoom)){
					if(null != premisesId){
						//分期不为空,同时校验项目及分期及房源类型相等字段相等
						if(prdDto.getProjectId().equals(String.valueOf(projectId))
								&& prdDto.getPremisesId().equals(String.valueOf(premisesId))
								&& industMarkFlag
								&& matchMonthFlag
								&& isRoomFlag){
							totalHaveReceive = totalHaveReceive.add(prdHaveReceive);
						}
					}else{
						//分期为空,只校验项目相等
						//分期不为空,同时校验项目及分期字段相等
						if(prdDto.getProjectId().equals(String.valueOf(projectId))
								&& industMarkFlag
								&& matchMonthFlag
								&& isRoomFlag){
							totalHaveReceive = totalHaveReceive.add(prdHaveReceive);
						}
					}
				}else{
					if(null != premisesId){
						//分期不为空,同时校验项目及分期及房源类型相等字段相等
						if(prdDto.getProjectId().equals(String.valueOf(projectId))
								&& prdDto.getPremisesId().equals(String.valueOf(premisesId))
								&& industMarkFlag
								&& matchMonthFlag){
							totalHaveReceive = totalHaveReceive.add(prdHaveReceive);
						}
					}else{
						//分期为空,只校验项目相等
						//分期不为空,同时校验项目及分期字段相等
						if(prdDto.getProjectId().equals(String.valueOf(projectId))
								&& industMarkFlag
								&& matchMonthFlag){
							totalHaveReceive = totalHaveReceive.add(prdHaveReceive);
						}
					}
				}
			}
		}
		pmoSaleData.setTotalRowCount(Long.valueOf(totalRowCount));
		pmoSaleData.setTotalCalculateArea(totalCalculateArea);
		pmoSaleData.setTotalSignAmount(totalSignAmount);
		pmoSaleData.setTotalHaveReceive(totalHaveReceive);
		return pmoSaleData;
	}

	/**
	 * 汇总项目-组团-业态动态数据
	 * @param yearMonth 汇总类型
	 * @param type 汇总类型
	 * @param projectId 项目
	 * @param premisesId 组团
	 * @param signedDataList 签约汇总
	 * @param receivedDataList 收款汇总
	 * @param allIndustList 业态汇总
	 * @return
	 */
	private List<DynamiSalesDataExtend> createIndustDataList(String yearMonth, String type, Long projectId, Long premisesId, List<PmoSignedDataDto> signedDataList, List<PmoReceivedDataDto> receivedDataList, List<ProjectPremisesIndustData> allIndustList) {

		List<DynamiSalesDataExtend> resultList = new ArrayList<DynamiSalesDataExtend>();
		BigDecimal unit = new BigDecimal("10000");
		// 新逻辑，查询项目自己对应的所有业态信息
		//组装业态List,需区分项目还是组团
		List<ProjectPremisesIndustData> industList = filterIndust(type, allIndustList);
		if(null != industList && industList.size() > 0){

			BaseCodeValueDto bcvDto = new BaseCodeValueDto();
			bcvDto.setCodeType(CodeTypeEnum.CUSTOMER_02.getNo());
			Map<String, BaseCodeValueDto> bcvMap = baseCodeValueService.selectBcvMap(bcvDto);

			for (ProjectPremisesIndustData ppid : industList) {
				String industMark = ppid.getIndustMark();
				if (StringUtils.isBlank(industMark)) {
					continue;
				}

				// 查询M2系统业态参数表
				bcvDto = bcvMap.get(industMark);
				if (null == bcvDto) {
					continue;
				}
				String pmoIndustMark = bcvDto.getCodeValue();
				DynamiSalesDataExtend dsde = new DynamiSalesDataExtend();
				dsde.setIndustValue(bcvDto.getCodeName());
				dsde.setIndustKey(bcvDto.getTypeName());
				dsde.setId(bcvDto.getId());
				dsde.setParentId(bcvDto.getTypeId());
				dsde.setProjectId(projectId);
				dsde.setIndustMark(pmoIndustMark);
				dsde.setMonth(yearMonth.replace("-", ""));

				//此处疑惑: 字段monthActualSalesAmount,monthActualBackAmount
				//原统计的是业态下的所有金额,而不是月金额.现已改成月金额.
				//如果需要变更成统计年金额,将filterPmoSaleData方法中的最后一个字段设为null即可
				PmoSaleData pmoSaleData = filterPmoSaleData(projectId, premisesId, String.valueOf(bcvDto.getId()), null,signedDataList, receivedDataList, null);

				BigDecimal totalSignAmount = null;
				if (null != pmoSaleData.getTotalSignAmount()) {
					totalSignAmount = MathUtil.bigDivide(pmoSaleData.getTotalSignAmount(), unit, 6);
				}
				if (ppid.getTargetValue() == null) {
					ppid.setTargetValue(BigDecimal.ZERO);
				}
				if (pmoIndustMark.equals(IndustMarkEnums.INDUSTMARKENUMS_PARKINSPACE.getCode())) {
					// 已售车位数
					if (null != pmoSaleData.getTotalCalculateArea()
							&& pmoSaleData.getTotalCalculateArea().compareTo(BigDecimal.ZERO) != 0) {
						dsde.setSoldParkinSpace(pmoSaleData.getTotalCalculateArea().intValue());
					}
					// 未售车位 = 可售车位数-已售车位数
					if (pmoSaleData.getTotalCalculateArea() == null && ppid.getSalableAcreag() != null) {
						dsde.setTotalNoCalculateArea(ppid.getSalableAcreag());
					} else if (null != ppid.getSalableAcreag() && null != pmoSaleData.getTotalCalculateArea()) {
						dsde.setTotalNoCalculateArea(new BigDecimal(MathUtil.subtract(ppid.getSalableAcreag().doubleValue(),
								pmoSaleData.getTotalCalculateArea().doubleValue())));
					}
					// 车位动态货值=实际销售额+项目车位目标销售均价*未售车位数
					if (null != ppid.getTargetAveragPrice() && null != dsde.getTotalNoCalculateArea()) {
						if (totalSignAmount == null) {
							totalSignAmount = BigDecimal.ZERO;
						}
						double cwDynamiAveragPrice = MathUtil.add(totalSignAmount.doubleValue(), MathUtil.multiply(
								ppid.getTargetAveragPrice().doubleValue(), dsde.getTotalNoCalculateArea().doubleValue()));
						// 加自持货值
						dsde.setCwDynamiAveragPrice(new BigDecimal(cwDynamiAveragPrice));
					}
					// 车位动态均价=车位动态货值/可售车位数
					if (null != dsde.getCwDynamiAveragPrice() && null != ppid.getSalableAcreag()) {
						dsde.setAveragPriceOfParkinSpace(MathUtil
								.bigDivide(dsde.getCwDynamiAveragPrice(), ppid.getSalableAcreag(), 6).doubleValue());
					}
				} else {
					dsde.setTotalSalableAcreag(ppid.getSalableAcreag());
					// 动态货值=实际销售额+项目目标销售均价*未售面积
					// 未售面积
					BigDecimal notArea = null;
					// 已售面积
					BigDecimal convertTotalCalculateArea = null;
					if (pmoSaleData.getTotalCalculateArea() == null && ppid.getSalableAcreag() != null) {
						notArea = ppid.getSalableAcreag();
					} else if (null != ppid.getSalableAcreag() && null != pmoSaleData.getTotalCalculateArea()) {
						// 已售面积单位转换
						convertTotalCalculateArea = MathUtil.bigDivide(pmoSaleData.getTotalCalculateArea(), unit, 6);
						notArea = new BigDecimal(MathUtil.subtract(ppid.getSalableAcreag().doubleValue(),
								convertTotalCalculateArea.doubleValue()));
					}
					if (null != notArea && null != ppid.getTargetAveragPrice()) {
						// 动态货值
						if (totalSignAmount == null) {
							totalSignAmount = BigDecimal.ZERO;
						}
						double dynamiValue = MathUtil.add(totalSignAmount.doubleValue(), MathUtil
								.multiply(notArea.multiply(unit).doubleValue(), ppid.getTargetAveragPrice().doubleValue()));
						dsde.setDynamiValue(MathUtil.round(dynamiValue, 6));
					}
					// 已售面积
					dsde.setSoldAcreag(convertTotalCalculateArea == null ? null : convertTotalCalculateArea.doubleValue());
					// 未售面积
					dsde.setTotalNoCalculateArea(notArea);

					// 动态均价=动态货值/可售面积
					if (null != dsde.getDynamiValue() && null != ppid.getSalableAcreag()) {
						dsde.setDynamiAveragPrice(MathUtil
								.bigDivide(new BigDecimal(dsde.getDynamiValue()), ppid.getSalableAcreag().multiply(unit), 6)
								.doubleValue());
					}
				}
				//目标货值
				dsde.setTargetValue(targerValue(projectId, premisesId));
				// 实际销售额
				dsde.setMonthActualSalesAmount(
						totalSignAmount == null || totalSignAmount.compareTo(BigDecimal.ZERO) == 0 ? null
								: totalSignAmount);
				// 实际回款额
				if (null != pmoSaleData.getTotalHaveReceive()
						&& pmoSaleData.getTotalHaveReceive().compareTo(BigDecimal.ZERO) != 0) {
					dsde.setMonthActualBackAmount(MathUtil.bigDivide(pmoSaleData.getTotalHaveReceive(), unit, 6));
				}
				// 偏差原因
				dsde.setDeviationRemake(ppid.getDeviationRemake());
				resultList.add(dsde);
			}
		}
		return resultList;
	}
	
	public List<TargetValue> targerValue(Long projectId,Long premiseId){
		List<TargetValue> targetValueList = new ArrayList<>();
		if(projectId!=null && premiseId == null) {
			ProjectPmoDto projectPmoDto = new ProjectPmoDto();
			projectPmoDto.setProjectId(projectId);
			ProjectPmo projectPmo = projectPmoService.selectByDto(projectPmoDto);
			if(projectPmo.getTargetValue()!=null&&projectPmo.getTargetValueTime()!=null&&!StringUtils.isEmpty(projectPmo.getTargetValueVersion())){
			    TargetValue targetValue = new TargetValue();
			    targetValue.setTargetValue(projectPmo.getTargetValue().floatValue());
			    targetValue.setEffectStartTime(DateUtils.DateToString(projectPmo.getTargetValueTime(), DateStyle.YYYYMMDD.getValue()));
			    targetValue.setTargetValueVersion(projectPmo.getTargetValueVersion());
			    targetValueList.add(targetValue);
			}
		}else {
			ProjectPremisesPmoDto projectPremisesPmoDto = new ProjectPremisesPmoDto();
			projectPremisesPmoDto.setProjectId(projectId);
			projectPremisesPmoDto.setPremisesId(premiseId);
			ProjectPremisesPmo projectPremisesPmo = projectPremisesPmoService.selectByDto(projectPremisesPmoDto);
			if(projectPremisesPmo.getTargetValue()!=null && projectPremisesPmo.getTargetValueTime()!=null&& projectPremisesPmo.getTargetValueVersion() != null) {
				 TargetValue targetValue = new TargetValue();
				 targetValue.setTargetValue(projectPremisesPmo.getTargetValue().floatValue());
				 targetValue.setEffectStartTime(DateUtils.DateToString(projectPremisesPmo.getTargetValueTime(), DateStyle.YYYYMMDD.getValue()));
				 targetValue.setTargetValueVersion(projectPremisesPmo.getTargetValueVersion());
				 targetValueList.add(targetValue);
			}
		}
		return targetValueList;
	}

	@Override
	public ResponseList<SaleReturnPmo> querySaleReturnListPmo(Long projectId, Long premisesId,
			String saleReturnCode, String year) throws Exception {

		ResponseList<SaleReturnPmo> responseList = new ResponseList<SaleReturnPmo>();
		SaleReturnPmoDto srpDto = new SaleReturnPmoDto();
		srpDto.setSaleReturn(saleReturnCode);
		srpDto.setSaleYear(year);
		if (StringUtils.isEmpty(year)) {
			year = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
			srpDto.setSaleYear(year);
		}
		srpDto.setOrders("t.sale_month");
		srpDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		if (premisesId != null) { // 分期
			srpDto.setObjectType(ObjectTypeEnum.PREMISES.getNo());
			srpDto.setObjectId(premisesId);
		} else { // 项目
			srpDto.setObjectType(ObjectTypeEnum.PROJECT.getNo());
			srpDto.setObjectId(projectId);
		}
		List<SaleReturnPmo> saleReturnList = salereturnpmoservice.selectListByDto(srpDto);
		if (null != saleReturnList && saleReturnList.size() > 0) {

			PmoSaleDataDto psdDto = new PmoSaleDataDto();
			psdDto.setProjectId(projectId);
			psdDto.setCalYear(year);
			//签约记录业态统计
			List<PmoSignedDataDto> signedDataList = projectService.queryPmoSignedData(psdDto);
			//回款记录业态统计
			List<PmoReceivedDataDto> receivedDataList = projectService.queryPmoReceivedData(psdDto);

			BigDecimal unit = new BigDecimal("10000");
			for (SaleReturnPmo sale : saleReturnList) {
				// 实际销售额
				String yearMonth = sale.getSaleYear() + "-" + sale.getSaleMonth();
				PmoSaleData pmoSaleData = filterPmoSaleData(projectId, premisesId, null, null,signedDataList, receivedDataList, yearMonth);
				BigDecimal totalSignAmount = null;
				if (null != pmoSaleData) {
					if (saleReturnCode.equals(sale.getSaleReturn()) && saleReturnCode.equals(SaleReturnEnum.SALE.getNo())) {
						if (null != pmoSaleData.getTotalSignAmount()) {
							totalSignAmount = MathUtil.bigDivide(pmoSaleData.getTotalSignAmount(), unit, 6);
							sale.setSaleActual(totalSignAmount.toString());
						}
					} else if(saleReturnCode.equals(sale.getSaleReturn()) && saleReturnCode.equals(SaleReturnEnum.RETURN.getNo())){
						if (null != pmoSaleData.getTotalHaveReceive()) {
							totalSignAmount = MathUtil.bigDivide(pmoSaleData.getTotalHaveReceive(), unit, 6);
							sale.setSaleActual(totalSignAmount.toString());
						}
					}

					// 差额 = 计划 - 实际
					if (!StringUtils.isEmpty(sale.getSalePlan())) {
						if (totalSignAmount == null) {
							sale.setSaleDiff(sale.getSalePlan());
						} else {
							Double saleDiff = MathUtil.subtract(new Double(sale.getSalePlan()),
									totalSignAmount.doubleValue());
							sale.setSaleDiff(saleDiff.toString());
						}
					}
				}

			}
			responseList.setEntity(saleReturnList);
		}
		return responseList;
	}

	static Map<String, Date> dateConvert(String month) {
		Map<String, Date> map = new HashMap<String, Date>();
		Date dateFormat = new Date();
		if(month.indexOf("-") > 0){
			dateFormat = DateUtils.StringToDate(month, DateStyle.YYYY_MM);
		}else{
			dateFormat = DateUtils.StringToDate(month, DateStyle.YYYYMM);
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(dateFormat);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		Date firstDayOfMonth = calendar.getTime();
		calendar.add(Calendar.MONTH, 1);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		Date lastDayOfMonth = calendar.getTime();
		String beginDate = DateUtils.formatDate(firstDayOfMonth, DateStyle.YYYY_MM_DD.getValue()) + " 00:00:00";
		String endDate = DateUtils.formatDate(lastDayOfMonth, DateStyle.YYYY_MM_DD.getValue()) + " 23:59:59";
		map.put("beginDate", DateUtils.StringToDate(beginDate));
		map.put("endDate", DateUtils.StringToDate(endDate));
		return map;
	}

}
